from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_login import login_required, current_user, login_user, logout_user
from urllib.parse import urlparse
from datetime import datetime
import mistune
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import html
from pygments.util import ClassNotFound
from slugify import slugify
import re
from app import db
from app.models import User, Post, Category, Tag, Comment
from app.forms import LoginForm, PostForm, CommentForm, CategoryForm, TagForm

# 创建蓝图
main_bp = Blueprint('main', __name__)
auth_bp = Blueprint('auth', __name__)
admin_bp = Blueprint('admin', __name__)

# Markdown渲染器配置
class HighlightRenderer(mistune.HTMLRenderer):
    def block_code(self, code, info=None):
        if info:
            try:
                lexer = get_lexer_by_name(info, stripall=True)
            except ClassNotFound:
                lexer = get_lexer_by_name('text', stripall=True)
        else:
            lexer = get_lexer_by_name('text', stripall=True)
        
        formatter = html.HtmlFormatter(style='github', noclasses=True)
        return highlight(code, lexer, formatter)
    
    def block_quote(self, text):
        return f'<blockquote class="blockquote">{text}</blockquote>'
    
    def linebreak(self):
        return '<br>\n'

markdown = mistune.create_markdown(renderer=HighlightRenderer(), plugins=['strikethrough'])

def process_math_formulas(html_content):
    """处理HTML内容中的数学公式"""
    # 先处理块级数学公式 $$ ... $$
    html_content = re.sub(r'\$\$([^$]+)\$\$', r'<div class="math-block">$$\1$$</div>', html_content, flags=re.DOTALL)
    
    # 再处理行内数学公式 \( ... \)
    html_content = re.sub(r'\\\(([^)]+)\\\)', r'<span class="math-inline">\\(\1\\)</span>', html_content)
    
    # 最后处理行内数学公式 $ ... $ (但不在$$块中)
    html_content = re.sub(r'(?<!\$)\$([^$]+)\$(?!\$)', r'<span class="math-inline">$\1$</span>', html_content)
    
    return html_content

def generate_slug(title):
    """生成文章slug，支持中文字符"""
    # 使用python-slugify处理，并添加中文支持
    slug = slugify(title, separator='-', lowercase=True)
    
    # 如果slug为空（纯中文标题），使用拼音或保留部分字符
    if not slug:
        # 简单的中文处理：保留部分字符并转换为拼音
        try:
            from pypinyin import lazy_pinyin
            slug = '-'.join(lazy_pinyin(title))
        except:
            # 如果pypinyin库不可用，使用简单的字符替换
            slug = re.sub(r'[^\w\s-]', '', title)
            slug = re.sub(r'[-\s]+', '-', slug)
    
    # 确保slug不为空
    if not slug:
        slug = 'post-' + str(int(datetime.utcnow().timestamp()))
    
    return slug

# 前台路由
@main_bp.route('/')
def index():
    """首页"""
    page = request.args.get('page', 1, type=int)
    posts = Post.query.filter_by(is_published=True)\
        .order_by(Post.created_at.desc())\
        .paginate(page=page, per_page=current_app.config['POSTS_PER_PAGE'], error_out=False)
    
    categories = Category.query.all()
    tags = Tag.query.all()
    
    return render_template('index.html', posts=posts, categories=categories, tags=tags)

@main_bp.route('/post/<slug>')
def post_detail(slug):
    """文章详情页"""
    post = Post.query.filter_by(slug=slug, is_published=True).first_or_404()
    
    # 增加浏览次数
    post.view_count += 1
    db.session.commit()
    
    # 获取相关文章
    related_posts = Post.query.filter(
        Post.category_id == post.category_id,
        Post.id != post.id,
        Post.is_published == True
    ).limit(3).all()
    
    # 评论表单
    form = CommentForm()
    
    # 获取已审核的评论
    comments = post.comments.filter_by(is_approved=True, is_spam=False)\
        .order_by(Comment.created_at.desc()).all()
    
    return render_template('post.html', post=post, related_posts=related_posts, 
                         form=form, comments=comments)

@main_bp.route('/preview/<slug>')
@login_required
def preview_post(slug):
    """文章预览页面（仅限管理员）"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    post = Post.query.filter_by(slug=slug).first_or_404()
    
    # 获取相关文章
    related_posts = Post.query.filter(
        Post.category_id == post.category_id,
        Post.id != post.id,
        Post.is_published == True
    ).limit(3).all()
    
    # 评论表单（预览模式下不显示）
    form = None
    
    # 获取已审核的评论
    comments = post.comments.filter_by(is_approved=True, is_spam=False)\
        .order_by(Comment.created_at.desc()).all()
    
    return render_template('post.html', post=post, related_posts=related_posts, 
                         form=form, comments=comments, is_preview=True)

@main_bp.route('/category/<slug>')
def category_posts(slug):
    """分类文章列表"""
    category = Category.query.filter_by(slug=slug).first_or_404()
    page = request.args.get('page', 1, type=int)
    
    posts = Post.query.filter_by(category_id=category.id, is_published=True)\
        .order_by(Post.created_at.desc())\
        .paginate(page=page, per_page=current_app.config['POSTS_PER_PAGE'], error_out=False)
    
    return render_template('category.html', category=category, posts=posts)

@main_bp.route('/tag/<slug>')
def tag_posts(slug):
    """标签文章列表"""
    tag = Tag.query.filter_by(slug=slug).first_or_404()
    page = request.args.get('page', 1, type=int)
    
    posts = Post.query.join(Post.tags).filter(Tag.slug == slug, Post.is_published == True)\
        .order_by(Post.created_at.desc())\
        .paginate(page=page, per_page=current_app.config['POSTS_PER_PAGE'], error_out=False)
    
    return render_template('tag.html', tag=tag, posts=posts)

@main_bp.route('/search')
def search():
    """搜索功能"""
    query = request.args.get('q', '')
    page = request.args.get('page', 1, type=int)
    
    if query:
        posts = Post.query.filter(
            Post.title.contains(query) | Post.content.contains(query),
            Post.is_published == True
        ).order_by(Post.created_at.desc())\
        .paginate(page=page, per_page=current_app.config['POSTS_PER_PAGE'], error_out=False)
    else:
        posts = None
    
    return render_template('search.html', posts=posts, query=query)

@main_bp.route('/post/<int:post_id>/comment', methods=['POST'])
def add_comment(post_id):
    """添加评论"""
    post = Post.query.get_or_404(post_id)
    form = CommentForm()
    
    if form.validate_on_submit():
        comment = Comment(
            content=form.content.data,
            post_id=post_id,
            guest_name=form.name.data,
            guest_email=form.email.data,
            guest_website=form.website.data
        )
        
        # 如果是登录用户，关联用户ID
        if current_user.is_authenticated:
            comment.author_id = current_user.id
            comment.is_approved = True  # 登录用户评论自动审核
        
        db.session.add(comment)
        db.session.commit()
        
        flash('评论已提交，等待审核！', 'success')
        return redirect(url_for('main.post_detail', slug=post.slug))
    
    return redirect(url_for('main.post_detail', slug=post.slug))

# 认证路由
@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
    """登录页面"""
    if current_user.is_authenticated:
        return redirect(url_for('admin.dashboard'))
    
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            login_user(user, remember=form.remember_me.data)
            next_page = request.args.get('next')
            if not next_page or urlparse(next_page).netloc != '':
                next_page = url_for('admin.dashboard')
            return redirect(next_page)
        flash('用户名或密码错误', 'error')
    
    return render_template('auth/login.html', form=form)

@auth_bp.route('/logout')
@login_required
def logout():
    """退出登录"""
    logout_user()
    return redirect(url_for('main.index'))

# 后台管理路由
@admin_bp.route('/')
@login_required
def dashboard():
    """管理后台首页"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    stats = {
        'total_posts': Post.query.count(),
        'published_posts': Post.query.filter_by(is_published=True).count(),
        'total_comments': Comment.query.count(),
        'pending_comments': Comment.query.filter_by(is_approved=False).count(),
        'total_categories': Category.query.count(),
        'total_tags': Tag.query.count()
    }
    
    recent_posts = Post.query.order_by(Post.created_at.desc()).limit(5).all()
    recent_comments = Comment.query.order_by(Comment.created_at.desc()).limit(5).all()
    
    return render_template('admin/dashboard.html', stats=stats, 
                         recent_posts=recent_posts, recent_comments=recent_comments)

@admin_bp.route('/posts')
@login_required
def posts():
    """文章管理"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    page = request.args.get('page', 1, type=int)
    posts = Post.query.order_by(Post.created_at.desc())\
        .paginate(page=page, per_page=20, error_out=False)
    
    return render_template('admin/posts.html', posts=posts)

@admin_bp.route('/posts/new', methods=['GET', 'POST'])
@login_required
def new_post():
    """新建文章"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    form = PostForm()
    form.category_id.choices = [(c.id, c.name) for c in Category.query.all()]
    
    if form.validate_on_submit():
        post = Post(
            title=form.title.data,
            slug=generate_slug(form.title.data),
            content=form.content.data,
            content_html=process_math_formulas(markdown(form.content.data)),
            excerpt=form.excerpt.data,
            is_published=form.is_published.data,
            is_featured=form.is_featured.data,
            author_id=current_user.id,
            category_id=form.category_id.data if form.category_id.data else None
        )
        
        # 处理标签
        if form.tags.data:
            tag_names = [tag.strip() for tag in form.tags.data.split(',')]
            for tag_name in tag_names:
                tag = Tag.query.filter_by(name=tag_name).first()
                if not tag:
                    tag = Tag(name=tag_name, slug=generate_slug(tag_name))
                    db.session.add(tag)
                post.tags.append(tag)
        
        db.session.add(post)
        db.session.commit()
        
        flash('文章创建成功！', 'success')
        return redirect(url_for('admin.posts'))
    
    return render_template('admin/post_form.html', form=form, title='新建文章')

@admin_bp.route('/posts/<int:id>/edit', methods=['GET', 'POST'])
@login_required
def edit_post(id):
    """编辑文章"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    post = Post.query.get_or_404(id)
    form = PostForm(obj=post)
    form.category_id.choices = [(c.id, c.name) for c in Category.query.all()]
    
    if form.validate_on_submit():
        post.title = form.title.data
        post.slug = generate_slug(form.title.data)
        post.content = form.content.data
        post.content_html = process_math_formulas(markdown(form.content.data))
        post.excerpt = form.excerpt.data
        post.is_published = form.is_published.data
        post.is_featured = form.is_featured.data
        post.category_id = form.category_id.data if form.category_id.data else None
        post.updated_at = datetime.utcnow()
        
        # 处理标签
        post.tags.clear()
        if form.tags.data:
            tag_names = [tag.strip() for tag in form.tags.data.split(',')]
            for tag_name in tag_names:
                tag = Tag.query.filter_by(name=tag_name).first()
                if not tag:
                    tag = Tag(name=tag_name, slug=generate_slug(tag_name))
                    db.session.add(tag)
                post.tags.append(tag)
        
        db.session.commit()
        flash('文章更新成功！', 'success')
        return redirect(url_for('admin.posts'))
    
    # 预填充标签
    form.tags.data = ', '.join([tag.name for tag in post.tags])
    
    return render_template('admin/post_form.html', form=form, post=post, title='编辑文章')

@admin_bp.route('/posts/<int:id>/delete', methods=['POST'])
@login_required
def delete_post(id):
    """删除文章"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    post = Post.query.get_or_404(id)
    db.session.delete(post)
    db.session.commit()
    
    flash('文章删除成功！', 'success')
    return redirect(url_for('admin.posts'))

@admin_bp.route('/comments')
@login_required
def comments():
    """评论管理"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    page = request.args.get('page', 1, type=int)
    comments = Comment.query.order_by(Comment.created_at.desc())\
        .paginate(page=page, per_page=20, error_out=False)
    
    return render_template('admin/comments.html', comments=comments)

@admin_bp.route('/comments/<int:id>/approve', methods=['POST'])
@login_required
def approve_comment(id):
    """审核通过评论"""
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': '权限不足'})
    
    comment = Comment.query.get_or_404(id)
    comment.is_approved = True
    db.session.commit()
    
    return jsonify({'success': True, 'message': '评论已审核通过'})

@admin_bp.route('/comments/<int:id>/spam', methods=['POST'])
@login_required
def spam_comment(id):
    """标记评论为垃圾"""
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': '权限不足'})
    
    comment = Comment.query.get_or_404(id)
    comment.is_spam = True
    db.session.commit()
    
    return jsonify({'success': True, 'message': '评论已标记为垃圾'})

@admin_bp.route('/comments/<int:id>/delete', methods=['POST'])
@login_required
def delete_comment(id):
    """删除评论"""
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': '权限不足'})
    
    comment = Comment.query.get_or_404(id)
    db.session.delete(comment)
    db.session.commit()
    
    return jsonify({'success': True, 'message': '评论已删除'})

@admin_bp.route('/categories', methods=['GET', 'POST'])
@login_required
def categories():
    """分类管理"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    categories = Category.query.all()
    form = CategoryForm()
    
    if form.validate_on_submit():
        category = Category(
            name=form.name.data,
            slug=generate_slug(form.name.data),
            description=form.description.data
        )
        db.session.add(category)
        db.session.commit()
        flash('分类创建成功！', 'success')
        return redirect(url_for('admin.categories'))
    
    return render_template('admin/categories.html', categories=categories, form=form)

@admin_bp.route('/tags', methods=['GET', 'POST'])
@login_required
def tags():
    """标签管理"""
    if not current_user.is_admin:
        flash('权限不足', 'error')
        return redirect(url_for('main.index'))
    
    tags = Tag.query.all()
    form = TagForm()
    
    if form.validate_on_submit():
        tag = Tag(
            name=form.name.data,
            slug=generate_slug(form.name.data)
        )
        db.session.add(tag)
        db.session.commit()
        flash('标签创建成功！', 'success')
        return redirect(url_for('admin.tags'))
    
    return render_template('admin/tags.html', tags=tags, form=form)

@admin_bp.route('/tags/<int:id>/delete', methods=['POST'])
@login_required
def delete_tag(id):
    """删除标签"""
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': '权限不足'})
    
    tag = Tag.query.get_or_404(id)
    
    # 检查是否有文章使用该标签
    post_count = tag.posts.count()
    if post_count > 0:
        return jsonify({'success': False, 'message': f'无法删除标签，还有 {post_count} 篇文章使用该标签'})
    
    db.session.delete(tag)
    db.session.commit()
    
    return jsonify({'success': True, 'message': '标签删除成功'})

@admin_bp.route('/tags/<int:id>/edit', methods=['POST'])
@login_required
def edit_tag(id):
    """编辑标签"""
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': '权限不足'})
    
    tag = Tag.query.get_or_404(id)
    data = request.get_json()
    
    if not data or 'name' not in data:
        return jsonify({'success': False, 'message': '缺少标签名称'})
    
    new_name = data['name'].strip()
    if not new_name:
        return jsonify({'success': False, 'message': '标签名称不能为空'})
    
    # 检查名称是否已存在
    existing_tag = Tag.query.filter(Tag.name == new_name, Tag.id != id).first()
    if existing_tag:
        return jsonify({'success': False, 'message': '标签名称已存在'})
    
    tag.name = new_name
    tag.slug = generate_slug(new_name)
    db.session.commit()
    
    return jsonify({'success': True, 'message': '标签更新成功'})

@admin_bp.route('/categories/<int:id>/delete', methods=['POST'])
@login_required
def delete_category(id):
    """删除分类"""
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': '权限不足'})
    
    category = Category.query.get_or_404(id)
    
    # 检查是否有文章使用该分类
    post_count = category.posts.count()
    if post_count > 0:
        return jsonify({'success': False, 'message': f'无法删除分类，还有 {post_count} 篇文章使用该分类'})
    
    db.session.delete(category)
    db.session.commit()
    
    return jsonify({'success': True, 'message': '分类删除成功'})

@admin_bp.route('/categories/<int:id>/edit', methods=['POST'])
@login_required
def edit_category(id):
    """编辑分类"""
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': '权限不足'})
    
    category = Category.query.get_or_404(id)
    data = request.get_json()
    
    if not data or 'name' not in data:
        return jsonify({'success': False, 'message': '缺少分类名称'})
    
    new_name = data['name'].strip()
    if not new_name:
        return jsonify({'success': False, 'message': '分类名称不能为空'})
    
    # 检查名称是否已存在
    existing_category = Category.query.filter(Category.name == new_name, Category.id != id).first()
    if existing_category:
        return jsonify({'success': False, 'message': '分类名称已存在'})
    
    category.name = new_name
    category.slug = generate_slug(new_name)
    if 'description' in data:
        category.description = data['description'].strip()
    
    db.session.commit()
    
    return jsonify({'success': True, 'message': '分类更新成功'})

